package com.toonly.tests;

import java.lang.reflect.*;
import java.util.List;

public class TypeTest {

    public static class A<T> {
        public int anInt;
        public List<String> anList;
        public List<T[]> anOtherList;
        public List<? extends String> the3rdList;
        public List<? super String> the4thList;
        public String[] strings;
        public TypeVariable[] typeVariables;
        public ParameterizedType[] parameterizedTypes;
    }

    public static void main(String[] args) {
        Field[] declaredFields = A.class.getDeclaredFields();
        System.out.println(declaredFields.length);

        for (Field field : declaredFields) {
            System.out.println(field.getType());
            Type genericType = field.getGenericType();
            printType(genericType);
            System.out.println();
        }
    }

    public static void printType(Type type) {
        System.out.println(type);
        System.out.println(type.getClass());

        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) type;
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            System.out.println(actualTypeArguments.length);

            for (Type actualTypeArgument : actualTypeArguments) {
                printType(actualTypeArgument);
            }
        }

        if (type instanceof TypeVariable) {
            TypeVariable typeVariable = (TypeVariable) type;
            System.out.println(typeVariable.getGenericDeclaration());
            Type[] bounds = typeVariable.getBounds();
            System.out.println(bounds.length);

            for (Type bound : bounds) {
                printType(bound);
            }
        }

        if (type instanceof WildcardType) {
            WildcardType wildcardType = (WildcardType) type;
            Type[] lowerBounds = wildcardType.getLowerBounds();
            System.out.println(lowerBounds.length);

            for (Type lowerBound : lowerBounds) {
                printType(lowerBound);
            }

            Type[] upperBounds = wildcardType.getUpperBounds();
            System.out.println(upperBounds.length);

            for (Type upperBound : upperBounds) {
                printType(upperBound);
            }
        }

        if (type instanceof GenericArrayType) {
            GenericArrayType genericArrayType = (GenericArrayType) type;
            Type genericComponentType = genericArrayType.getGenericComponentType();
            System.out.println(genericComponentType);

            printType(genericComponentType);
        }
    }
}
